package com.laker.autotest.desktop;

import com.github.kwhat.jnativehook.GlobalScreen;
import com.github.kwhat.jnativehook.keyboard.NativeKeyEvent;
import com.github.kwhat.jnativehook.keyboard.NativeKeyListener;
import com.github.kwhat.jnativehook.mouse.*;
import lombok.Getter;

import java.util.ArrayList;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;

public class EventListenerManager {
    @Getter
    private final List<ScriptEvent> scriptEvents = new ArrayList<>();
    private boolean isRecording = false;
    private final NativeKeyListener keyListener;
    private final NativeMouseListener mouseListener;
    private final NativeMouseMotionListener mouseMotionListener;
    private final NativeMouseWheelListener mouseWheelListener;
    private final EventListModel eventListModel;

    public EventListenerManager(EventListModel eventListModel) {
        this.eventListModel = eventListModel;
        keyListener = new NativeKeyListener() {
            @Override
            public void nativeKeyPressed(NativeKeyEvent nativeKeyEvent) {
                if (isRecording) {
                    scriptEvents.add(ScriptEvent.keyPress(nativeKeyEvent));
                    eventListModel.addElement("按键按下: " + NativeKeyEvent.getKeyText(nativeKeyEvent.getKeyCode()));
                }
            }

            @Override
            public void nativeKeyReleased(NativeKeyEvent nativeKeyEvent) {
                if (isRecording) {
                    scriptEvents.add(ScriptEvent.keyRelease(nativeKeyEvent));
                    eventListModel.addElement("按键释放: " + NativeKeyEvent.getKeyText(nativeKeyEvent.getKeyCode()));
                }
            }

            @Override
            public void nativeKeyTyped(NativeKeyEvent nativeKeyEvent) {
                if (isRecording) {
                    scriptEvents.add(ScriptEvent.keyTyped(nativeKeyEvent));
                    eventListModel.addElement("按键输入: " + nativeKeyEvent.getKeyChar());
                }
            }
        };
        mouseListener = new NativeMouseListener() {
            @Override
            public void nativeMouseClicked(NativeMouseEvent nativeMouseEvent) {
                if (isRecording) {
                    scriptEvents.add(ScriptEvent.mouseClick(nativeMouseEvent.getX(), nativeMouseEvent.getY(), nativeMouseEvent.getButton()));
                    eventListModel.addElement("鼠标点击: " + nativeMouseEvent.getButton() + " at (" + nativeMouseEvent.getX() + ", " + nativeMouseEvent.getY() + ")");
                }
            }

            @Override
            public void nativeMousePressed(NativeMouseEvent nativeMouseEvent) {
                if (isRecording) {
                    scriptEvents.add(ScriptEvent.mousePress(nativeMouseEvent.getX(), nativeMouseEvent.getY(), nativeMouseEvent.getButton()));
                    eventListModel.addElement("鼠标按下: " + nativeMouseEvent.getButton() + " at (" + nativeMouseEvent.getX() + ", " + nativeMouseEvent.getY() + ")");
                }
            }

            @Override
            public void nativeMouseReleased(NativeMouseEvent nativeMouseEvent) {
                if (isRecording) {
                    scriptEvents.add(ScriptEvent.mouseRelease(nativeMouseEvent.getX(), nativeMouseEvent.getY(), nativeMouseEvent.getButton()));
                    eventListModel.addElement("鼠标释放: " + nativeMouseEvent.getButton() + " at (" + nativeMouseEvent.getX() + ", " + nativeMouseEvent.getY() + ")");
                }
            }
        };
        mouseMotionListener = new NativeMouseMotionListener() {
            @Override
            public void nativeMouseMoved(NativeMouseEvent nativeMouseEvent) {
                if (isRecording) {
                    scriptEvents.add(ScriptEvent.mouseMove(nativeMouseEvent.getX(), nativeMouseEvent.getY()));
                    eventListModel.addElement("鼠标移动: (" + nativeMouseEvent.getX() + ", " + nativeMouseEvent.getY() + ")");
                }
            }

            @Override
            public void nativeMouseDragged(NativeMouseEvent nativeMouseEvent) {
                if (isRecording) {
                    scriptEvents.add(ScriptEvent.mouseDrag(
                        nativeMouseEvent.getX(),
                        nativeMouseEvent.getY(),
                        nativeMouseEvent.getX(),
                        nativeMouseEvent.getY()
                    ));
                    eventListModel.addElement("鼠标拖动: (" + nativeMouseEvent.getX() + ", " + nativeMouseEvent.getY() + ")");
                }
            }
        };
        mouseWheelListener = new NativeMouseWheelListener() {
            @Override
            public void nativeMouseWheelMoved(NativeMouseWheelEvent nativeMouseWheelEvent) {
                if (isRecording) {
                    scriptEvents.add(ScriptEvent.mouseWheel(nativeMouseWheelEvent.getX(), nativeMouseWheelEvent.getY(), nativeMouseWheelEvent.getWheelRotation()));
                    eventListModel.addElement("鼠标滚轮: " + nativeMouseWheelEvent.getWheelRotation() + " at (" + nativeMouseWheelEvent.getX() + ", " + nativeMouseWheelEvent.getY() + ")");
                }
            }
        };
    }

    public void startRecord() {
        isRecording = true;
        scriptEvents.clear();
        eventListModel.clear();
        eventListModel.addElement("[录制开始]");
        try {
            if (!GlobalScreen.isNativeHookRegistered()) {
                Logger logger = Logger.getLogger(GlobalScreen.class.getPackage().getName());
                logger.setLevel(Level.OFF);
                logger.setUseParentHandlers(false);
                GlobalScreen.registerNativeHook();
            }
        } catch (Exception e) {
            return;
        }
        GlobalScreen.addNativeKeyListener(keyListener);
        GlobalScreen.addNativeMouseListener(mouseListener);
        GlobalScreen.addNativeMouseMotionListener(mouseMotionListener);
        GlobalScreen.addNativeMouseWheelListener(mouseWheelListener);
    }

    public void stopRecord() {
        isRecording = false;
        eventListModel.addElement("[录制结束]");
        GlobalScreen.removeNativeKeyListener(keyListener);
        GlobalScreen.removeNativeMouseListener(mouseListener);
        GlobalScreen.removeNativeMouseMotionListener(mouseMotionListener);
        GlobalScreen.removeNativeMouseWheelListener(mouseWheelListener);
    }
}